前幾篇我們介紹了透過 Struct 可以創建自己的類型和儲存複雜數據的類型,但有時候開發上會需要更具擴展性和可管理性的東西,也就是今天要介紹的向量 (Vector)
Vector 是用於存儲數據集合的內置類型。它是任何類型(但只能一種)集合的通用解決方案。因為它的功能是由虛擬機提供給的;使用它的唯一方法是使用 Move 標準庫
和native
函數。
通常,vector 可以自動推斷類型,如果無法推斷則可以使用之前所提到的,顯示指定類型。
vector<T>[]: vector<T>
vecctor<T>[e1, ..., en]: vector<T>
(vector[]: vector<bool>);
(vector[0u8, 1u8, 2u8]: vector<u8>);
(vector<u128>[]: vector<u128>);
(vector<address>[@0x42, @0x100]: vector<address>);
Move 中向量的一個常見用例是 “byte arrays” vector<u8>
這些值通常用於加密目的,例如公鑰或hash 結果。這些值非常常見,以至於提供了特定的語法以使值更具可讀性,而不必使用以數字形式指定vector[]
,目前可以資源兩種 type: byte srings 和 hex strings (十六進制)。
字節字符串是以 b
為前綴的帶引號的字符串文字,例如b"Hello!\n"
這些是允許轉義序列的 ASCII 編碼字符串。目前,支持的轉義序列是
十六進製字符串是以 x
為前綴的帶引號的字符串文字,例如x"48656C6C6F210A"
每個字節對,範圍從00
到FF
,都被解釋為十六進制編碼u8
值。所以每個字節對對應於結果中的一個條目vector<u8>
script {
fun byte_and_hex_strings() {
assert!(b"" == x"", 0);
assert!(b"Hello!\n" == x"48656C6C6F210A", 1);
assert!(b"\x48\x65\x6C\x6C\x6F\x21\x0A" == x"48656C6C6F210A", 2);
assert!(
b"\"Hello\tworld!\"\n \r \\Null=\0" ==
x"2248656C6C6F09776F726C6421220A200D205C4E756C6C3D00",
3
);
}
}
vectorStd::Vector
通過 Move 標準庫中的模塊支持以下操作:
use Std::Vector;
let v = Vector::empty<u64>();
Vector::push_back(&mut v, 5);
Vector::push_back(&mut v, 6);
assert!(*Vector::borrow(&v, 0) == 5, 42);
assert!(*Vector::borrow(&v, 1) == 6, 42);
assert!(Vector::pop_back(&mut v) == 6, 42);
assert!(Vector::pop_back(&mut v) == 5, 42);
vector 的能力一樣受到元素類型能力影響,如果使用包含沒有元素的向量,需要而外設定顯式銷毀
Vector::destroy_empty
或是給予 drop 能力。
需要注意是,如果使用顯式銷毀,但元素數量不等於 0,將會在運行時終止。
fun destroy_any_vector<T>(vec: vector<T>) {
Vector::destroy_empty(vec) // deleting this line will cause a compiler error
}
fun destroy_droppable_vector<T: drop>(vec: vector<T>) {
// valid!
}
同樣,除非元素類型具有 copy 能力,否則也無法複製向量 ,複製大型的向量將會耗費巨大費用,因此需要特別注意使用。
讓我們 Move to Day 16
相關資料
Move 標準庫: https://github.com/diem/move/tree/main/language/move-stdlib/sources